﻿using Ec.NETCoreFramework.Common.Core.Helpers;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Threading.Tasks;
using System.IO;
using Ec.NETCoreFramework.Common.Core;

namespace Ec.NETCoreFramework.Common.ValidateSign
{
    /// <summary>
    /// 中间件校验
    /// </summary>
    public class FrameworkValidate
    {
        private readonly RequestDelegate _next;
        private readonly ILogger _logger;
        private SignConfig _signConfig;

        public FrameworkValidate(RequestDelegate next, ILogger<FrameworkValidate> logger, SignConfig signConfig)
        {
            this._next = next;
            this._logger = logger;
            this._signConfig = signConfig;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext context)
        {
            try
            {
                var path = context.Request.Path.Value;
                var v = "1.0";
                if (!string.IsNullOrEmpty(_signConfig.VersionName)&&context.Request.Headers.ContainsKey(_signConfig.VersionName))
                {
                    v = context.Request.Headers[_signConfig.VersionName].FirstOrDefault();
                }
                
                if (_signConfig.IsDevelopment||context.Request.Method.ToLower() == "get"|| _signConfig.FilterRoute.Contains(path)||_signConfig.FilterVersion.Contains(v))
                {
                    await _next.Invoke(context);
                }
                else
                {
                    //校验
                    Stream stream = context.Request.Body;
                    string contenttype = context.Request.ContentType;
                    if (stream.CanRead)
                    {
                        using (var newRequest = new MemoryStream())
                        {
                            //替换request流
                            context.Request.Body = newRequest;
                            string requestString = string.Empty;
                            using (StreamReader reader = new StreamReader(stream))
                            {
                                requestString = await reader.ReadToEndAsync();
                            }
                            //进行校验
                            //to do。。。
                            SysParameter para =new ValidateParameter(_signConfig).Validate(requestString);
                            //写回
                            using (var writer = new StreamWriter(newRequest))
                            {
                                await writer.WriteAsync(requestString);
                                await writer.FlushAsync();
                                newRequest.Position = 0;
                                context.Request.Body = newRequest;
                                context.Request.ContentType = contenttype;
                                await _next.Invoke(context);
                            }
                            //await _next.Invoke(context);
                        }
                    }
                }

            }
            catch (Exception e)
            {
                await HandleException(context, FrameworkResponse.SystemErrorData(string.Empty,e.Message,e.HResult.ToString()));
            }
        }
   
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        private  async Task HandleException(HttpContext context, IResponse response)
        {
            _logger.LogError(response.Message);
            context.Response.StatusCode = StatusCodes.Status500InternalServerError;
            context.Response.ContentType = "application/json;charset=utf-8";
            string error = Json.ToJson(response);           
            await context.Response.WriteAsync(error);

        }
       
    }
}
